<?php

/**
 * Created by PhpStorm.
 * Author: ls
 * Time: 2023/9/11 11:29
 * Desc:
 */
trait Trait_Api_Image
{

    /**
     * 获取可访问的图标数组
     * @param $ico_ids
     * @return array
     */
    public function icons($ico_ids)
    {
        $data = array();
        if (!empty($ico_ids)) {
            $ico_ids = is_array($ico_ids) ? $ico_ids : explode(',', $ico_ids);
            $data    = DB::select('kind', 'picurl')
                ->from('icon')
                ->where('id', 'in', $ico_ids)
                ->execute()
                ->as_array();
            foreach ($data as &$r) {
                $r['litpic'] = $this->img_url($r['picurl']);
                unset($r['picurl']);
                // 获取图片宽高
                $image_info  = $this->get_image_size($r['litpic']);
                $r['width']  = $image_info['width'] ?? '0';
                $r['height'] = $image_info['height'] ?? '0';
            }
        }
        return $data;
    }

    /**
     * 图片绝对路径
     * @param $img_path
     * @param float $w
     * @param float $h
     * @return mixed|string
     */
    public function img_url($img_path, $w = 0, $h = 0)
    {
        $path = Common::img($img_path, $w, $h);
        return $this->reorganized_resource_url($path);
    }

    /**
     * 处理产品图片列表
     * @param string $pic_list 产品图片列表
     * @param bool $need_default_pic 是否需要默认图片
     * @return array
     */
    public function pic_list_url($pic_list, $need_default_pic = true)
    {
        $data = array();
        if ($pic_list) {
            $pic_list = Product::pic_list($pic_list);
            foreach ($pic_list as &$pic) {
                $url = $this->img_url($pic[0], 750, 750);
                array_push($data, $url);
            }
        }

        if ($need_default_pic && empty($data)) {
            $data = array(
                $this->img_url('')
            );
        }
        return $data;
    }

    /**
     * 将相对文件url换成绝对文件url
     * @param $url
     * @return mixed|string
     */
    public function reorganized_resource_url($url)
    {
        if (!empty($url)) {
            $http  = stripos(strtolower($url), 'http://');
            $https = stripos(strtolower($url), 'https://');
            if ($http === false && $https === false) {
                if (substr($url, 0, 8) == '/uploads') {
                    return common::get_main_host() . $url;
                } elseif (substr($url, 0, 7) == 'uploads') {
                    return common::get_main_host() . '/' . $url;
                } elseif (substr($url, 0, 2) == '//') {
                    $http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https:' : 'http:';
                    return $http_type . $url;
                } elseif (substr($url, 0, 4) == '/res') {
                    return common::get_main_host() . $url;
                } elseif (stripos($url, 'h5') !== false) {
                    return common::get_main_host() . '/' . $url;
                }
            } else {
                return $url;
            }
        }
        return $url;
    }

    /**
     * 获取会员头像
     * @param $url
     * @return mixed|string|string[]|null
     */
    public function get_member_header_pic($url)
    {
        // 判断url开头是否为`//`开头的地址
        if ($url) {
            $first = substr($url, 0, 2);
            if ($first == '//') { // 直接添加http
                $http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https:' : 'http:';
                return $http_type . $url;
            } else {
                return $this->img_url($url);
            }
        } else {  // 默认头像
            return $this->img_url(Common::member_nopic());
        }
    }

    /**
     * 保存base64图片
     * @param $base64_image_content
     * @param $path
     * @param $filename
     * @return false|string
     * @throws Kohana_Exception
     */
    public function save_base64_image($base64_image_content, $path, $filename = '')
    {
        //匹配出图片的格式
        if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)) {
            // 图片后缀
            $type = $result[2];
            // 根目录
            $dir = rtrim(BASEPATH . '/', '\\../');
            // 存放文件夹
            $new_file = $dir;
            // 循环查询文件是否存在
            $fileArr = explode('/', $path);
            foreach ($fileArr as $fileV) {
                if ($fileV) {
                    $new_file .= '/' . $fileV;
                    if (!file_exists($new_file)) {
                        //检查是否有该文件夹，如果没有就创建
                        mkdir($new_file, 0777);
                    }
                }
            }

            // 图片名
            $filename = $filename ? $filename : time() . rand('100000', '999999');
            $img      = $filename . ".{$type}";

            $new_filename = $new_file . '/' . $img; // 文件存放位置
            $resUrl       = $path . $img; // 保存成功后返回全路径
            // 检查文件是否存在
            if (file_exists($new_filename)) {
                //检查是否有该文件夹，如果没有就创建
                return $resUrl;
            }

            // 保存文件
            if (file_put_contents($new_filename, base64_decode(str_replace($result[1], '', $base64_image_content)))) {
                $config = Kohana::$config->load('image');
                foreach ($config as $k => $item) {
                    if (is_array($item) && $item['is_open'] && method_exists($item['callback'], 'move_image')) {
                        $value = $item['callback']::move_image($item, $resUrl);
                        if ($value) {
                            $resUrl = '/' . $value;
                        }
                    }
                }
                return $resUrl;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 上传视频
     * @param $base64_image_content
     * @param $path
     * @param $filename
     * @return false|string
     * @throws Kohana_Exception
     */
    public function save_base64_video($base64_image_content, $path, $filename = '')
    {
        //匹配出图片的格式
        if (preg_match('/^(data:\s*video\/(\w+);base64,)/', $base64_image_content, $result)) {
            // 图片后缀
            $type = $result[2];
            // 根目录
            $dir = rtrim(BASEPATH . '/', '\\../');
            // 存放文件夹
            $new_file = $dir;
            // 循环查询文件是否存在
            $fileArr = explode('/', $path);
            foreach ($fileArr as $fileV) {
                if ($fileV) {
                    $new_file .= '/' . $fileV;
                    if (!file_exists($new_file)) {
                        //检查是否有该文件夹，如果没有就创建
                        mkdir($new_file, 0777);
                    }
                }
            }

            // 图片名
            $filename = $filename ? $filename : time() . rand('100000', '999999');
            $img      = $filename . ".{$type}";

            $new_filename = $new_file . '/' . $img; // 文件存放位置
            $resUrl       = $path . $img; // 保存成功后返回全路径
            // 检查文件是否存在
            if (file_exists($new_filename)) {
                //检查是否有该文件夹，如果没有就创建
                return $resUrl;
            }

            // 保存文件
            if (file_put_contents($new_filename, base64_decode(str_replace($result[1], '', $base64_image_content)))) {
                $config = Kohana::$config->load('image');
                foreach ($config as $item) {
                    if (is_array($item) && $item['is_open'] && method_exists($item['callback'], 'move_image')) {
                        $value = $item['callback']::move_image($item, $resUrl);
                        if ($value) {
                            $resUrl = '/' . $value;
                        }
                    }
                }
                return $resUrl;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }


    /**
     * 获取远程图片的宽高和体积大小
     * @param string $url 远程图片的链接
     * @param string $type 获取远程图片资源的方式, 默认为 curl 可选 fread
     * @param boolean $isGetFilesize 是否获取远程图片的体积大小, 默认false不获取, 设置为 true 时 $type 将强制为 fread
     * @return false|array
     */
    public function get_image_size($url, $type = 'curl', $isGetFilesize = false)
    {

        // 从数据库获取
        $size = $this->get_image_size_database($url);
        if($size) {
            return $size;
        }
        // 若需要获取图片体积大小则默认使用fread 方式
        $type = $isGetFilesize ? 'fread' : $type;
        if ($type == 'fread') {
            // 或者使用 socket 二进制方式读取, 需要获取图片体积大小最好使用此方法
            $handle = fopen($url, 'rb');
            if (!$handle) return false;
            // 只取头部固定长度168字节数据
            $dataBlock = fread($handle, 168);
        } else {
            // 据说 CURL 能缓存DNS 效率比 socket 高
            $ch = curl_init($url);// 超时设置
            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
            // 取前面 168 个字符通过四张测试图读取宽高结果都没有问题,若获取不到数据可适当加大数值
            curl_setopt($ch, CURLOPT_RANGE, '0-167');// 跟踪301跳转
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// 返回结果
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            $dataBlock = curl_exec($ch);
            curl_close($ch);
            if (!$dataBlock)
                return false;
        }
        // 将读取的图片信息转化为图片路径并获取图片信息,经测试,这里的转化设置 jpeg 对获取png,gif的信息没有影响,无须分别设置
        // 有些图片虽然可以在浏览器查看但实际已被损坏可能无法解析信息
        $size = getimagesize('data://image/jpeg;base64,' . base64_encode($dataBlock));
        if (empty($size)) {
            return false;
        }
        $result['width']  = $size[0];
        $result['height'] = $size[1];
        // 保存到数据库
        $this->save_image_size_database($url, $result['width'], $result['height']);
        // 是否获取图片体积大小
        if ($isGetFilesize) {
            // 获取文件数据流信息
            $meta = stream_get_meta_data($handle);
            // nginx 的信息保存在 headers 里，apache 则直接在 wrapper_data
            $dataInfo = isset($meta['wrapper_data']['headers']) ? $meta['wrapper_data']['headers'] : $meta['wrapper_data'];
            foreach ($dataInfo as $va) {
                if (preg_match('/length/iU', $va)) {
                    $ts             = explode(':', $va);
                    $result['size'] = trim(array_pop($ts));
                    break;
                }
            }
        }
        if ($type == 'fread')
            fclose($handle);
        return $result;
    }

    /**
     * 数据库查询图片尺寸
     * @param $url
     * @return mixed|null
     */
    public function get_image_size_database($url)
    {
        $tag = MD5($url);
        return DB::select('width', 'height')
            ->from('image_size')
            ->where('tag', '=', $tag)
            ->execute()
            ->current();
    }

    /**
     * 保存图片尺寸
     * @param $url
     * @param $width
     * @param $height
     * @return void
     */
    public function save_image_size_database($url, $width, $height)
    {
        if ($url && $width && $height) {
            $tag = MD5($url);
            DB::query(Database::INSERT, "insert into `sline_image_size`(`tag`,`height`,`width`) values ('{$tag}','{$height}','{$width}') ON DUPLICATE KEY UPDATE `height`=VALUES(height),`width`=VALUES(width)")->execute();
        }
    }
}